home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et-2_2.lha / et2.2 / src / Text.C < prev    next >
C/C++ Source or Header  |  1990-12-04  |  10KB  |  593 lines

  1. //$Text,TextIter$
  2. #include "Text.h"
  3. #include "Error.h"
  4. #include "RegularExp.h"
  5. #include "Mark.h"
  6. #include "Port.h"
  7. #include "OrdColl.h"
  8.  
  9. //---- LineDesc --------------------------------------------------------
  10.  
  11. LineDesc::LineDesc(int b, int h)
  12. {
  13.     lnAscent = b;
  14.     lnHeight = h;
  15.  
  16. void LineDesc::Reset()
  17. {
  18.     lnAscent = 0;
  19.     lnHeight = 0;
  20. }
  21.  
  22. void LineDesc::Max(FontPtr f)
  23.     lnHeight =  max(lnHeight-lnAscent,f->Spacing()-f->Ascender()) +
  24.         max(f->Ascender(),lnAscent);
  25.     lnAscent =  max(f->Ascender(),lnAscent);
  26. }
  27.  
  28. void LineDesc::Max(LineDesc ld)
  29.     lnHeight =  max(lnHeight-lnAscent,ld.lnHeight - ld.lnAscent) +
  30.         max(ld.lnAscent,lnAscent);
  31.     lnAscent =  max(ld.lnAscent,lnAscent);
  32. }
  33.  
  34. void LineDesc::Max(int ascent, int height)
  35. {
  36.     lnHeight =  max(lnHeight-lnAscent,height-ascent) +
  37.         max(ascent,lnAscent);
  38.     lnAscent =  max(ascent,lnAscent);     
  39. }    
  40.  
  41. ostream& LineDesc::DisplayOn (ostream&s)
  42. {
  43.     return s << "Ascent=" << lnAscent << "/Height=" << lnHeight;
  44. }
  45.  
  46. //---- Text ------------------------------------------------------------
  47.  
  48. AbstractMetaImpl(Text, (TP(marks), TP(observers), 0));
  49.  
  50. Text::Text()
  51.     tabWidth = cTabw;
  52.     marks = 0;
  53.     observers= 0;
  54. }
  55.  
  56. Text::~Text()
  57. {   
  58.     if (marks) {
  59.     marks->FreeAll();
  60.     delete marks;
  61.     }   
  62.     if (observers) 
  63.     CleanupObservers(observers);
  64. }
  65.  
  66. void Text::InitNew()
  67. {
  68.     marks = 0;
  69.     tabWidth = cTabw;
  70. }
  71.  
  72. void Text::CalcIws (int width, int from, int *to, int *addSpace, 
  73.                         int *longBlanks, int *ntab)
  74. {
  75.     int nBlanks;
  76.     int ch;
  77.  
  78.     nBlanks = *addSpace = *longBlanks = *ntab = 0;
  79.  
  80.     for ( ;*to-1 >= from && ((*this)[*to-1] == ' ' || (*this)[*to-1] == '\t'); 
  81.                                     (*to)--) 
  82.     ;
  83.  
  84.     AutoTextIter ti(this,from,*to);
  85.     int w = TextWidth(from,*to);
  86.     while ((ch = ti()) != cEOT) {
  87.     if (ch == '\t') {
  88.         (*ntab)++;
  89.         nBlanks = 0;
  90.     }
  91.     else if (ch == ' ')
  92.         nBlanks++;
  93.     }
  94.     if (nBlanks) {
  95.     *longBlanks = (width - w) % nBlanks;
  96.     *addSpace = (width - w) / nBlanks;
  97.     }
  98. }
  99.  
  100. void Text::Cut(int from,int to)
  101. {
  102.     if (marks)
  103.     marks->Cut(from,to - from);
  104. }
  105.  
  106. void Text::Paste(TextPtr t, int from, int to)
  107. {
  108.     if (marks) {
  109.     if (from != to)
  110.         marks->Cut(from,to - from);
  111.     marks->Paste(from,t->Size()); 
  112.     }
  113. }
  114.  
  115. void Text::Copy(Text *, int , int)
  116. {
  117.     AbstractMethod("Copy");
  118. }
  119.  
  120. void Text::CopyInStr(byte*, int, int, int)
  121. {
  122.     AbstractMethod("CopyInStr");
  123. }
  124.  
  125. void Text::ReplaceWithStr(byte*, int)
  126. {
  127.     AbstractMethod("ReplaceWithStr");
  128. }
  129.  
  130. void Text::SetFStringVL(char *, va_list)
  131. {
  132.     AbstractMethod("SetFStringVL");
  133. }
  134.  
  135. void Text::SetFString(char *va_(fmt), ...)
  136. {
  137.     va_list ap;
  138.     va_start(ap,va_(fmt));
  139.     SetFStringVL(va_(fmt), ap);
  140.     va_end(ap);    
  141. }
  142.  
  143. byte *Text::GetTextAt(int, int)
  144. {
  145.     AbstractMethod("GetTextAt");
  146.     return 0;
  147. }
  148.  
  149. int Text::Search(RegularExp *rex, int *nMatched, int start, int range, 
  150.                          bool forward)
  151. {
  152.     int pos;
  153.     char *s = AsString();
  154.     if (forward) 
  155.     pos= rex->SearchForward (s, nMatched, start, Size(), range, 0);
  156.     else
  157.     pos= rex->SearchBackward (s, nMatched, start, Size(), range, 0); 
  158.     delete s;
  159.     return pos;
  160. }
  161.  
  162. Text *Text::GetScratchText(int) 
  163. {
  164.     return (TextPtr)this->New();
  165. }
  166.  
  167. TextPtr Text::Save(int, int)
  168. {
  169.     AbstractMethod("Save");
  170.     return 0;
  171. }
  172.  
  173. void Text::Insert(byte, int from, int to)
  174. {
  175.     if (marks) {
  176.     if (from != to)
  177.         marks->Cut(from,to - from);
  178.     marks->Paste(from,1); 
  179.     }
  180. }
  181.  
  182. void Text::Append(byte c)
  183. {
  184.     Insert(c, Size(), Size());
  185. }
  186.  
  187. static byte dummyc;
  188.  
  189. byte& Text::operator[](int )
  190. {
  191.     AbstractMethod("operator[]");
  192.     return dummyc;
  193. }
  194.  
  195. void Text::Empty (int)                                         
  196. {
  197.     AbstractMethod("Empty");
  198. }
  199.  
  200. int Text::Size ()                                         
  201. {
  202.     AbstractMethod("Size");
  203.     return 0;
  204. }
  205.  
  206. void Text::GetWordBoundaries(int at, int *start, int *end)
  207. {
  208.     register int i;
  209.  
  210.     if (!CheckRange(Size(), at, at))
  211.     return;
  212.  
  213.     for (i = at-1; i >= 0 && Isinword((*this)[i]); i--)
  214.     ;
  215.     *start = i+1; 
  216.     for (i = at; i < Size() && Isinword((*this)[i]); i++)
  217.     ; 
  218.     *end = i;
  219. }
  220.  
  221. void Text::GetParagraphBoundaries(int at,int *start,int *end)
  222. {
  223.     register int i, ch;
  224.  
  225.     if (!CheckRange(Size(), at, at))
  226.     return;
  227.  
  228.     for (i = at-1; i >= 0; i--) {
  229.     ch= (*this)[i];
  230.     if (ch == '\n' || ch == '\r')
  231.         break;
  232.     }
  233.     *start = i+1; 
  234.     for (i = at; i < Size(); i++) {
  235.     ch= (*this)[i];
  236.     if (ch == '\n' || ch == '\r')
  237.         break; 
  238.     }
  239.     *end= min(Size(), i+1);
  240. }
  241.  
  242. int Text::Tabulate(int x)
  243. {
  244.     if (tabWidth > 0) {
  245.     int n = x / tabWidth;
  246.     return ((n+1) * tabWidth - x);
  247.     }
  248.     return 0;
  249. }
  250.  
  251. int Text::SetTabWidth(int t)
  252. {
  253.     int ot= tabWidth;
  254.     tabWidth= t;
  255.     return ot;
  256. }
  257.  
  258. TextIter *Text::MakeIterator(int,int)
  259. {
  260.     AbstractMethod("MakeIterator ");
  261.     return 0;    
  262. }
  263.  
  264. void Text::SetFont(FontPtr fp) 
  265. {
  266.     font= fp;
  267. }
  268.  
  269. FontPtr Text::GetFont(int)
  270. {
  271.     return font;
  272. }
  273.  
  274. void Text::SetInk(Ink *c) 
  275. {
  276.     ink= c;
  277. }
  278.  
  279. Ink *Text::GetInk(int)
  280. {
  281.     return ink;
  282. }
  283.  
  284. FontPtr Text::SetDrawingState(int at)
  285. {
  286.     FontPtr fp= GetFont();
  287.     GrSetFont(GetFont(at));
  288.     GrSetTextPattern(GetInk());
  289.     return fp;        
  290. }
  291.  
  292. void Text::ResetCurrentStyle()
  293. {
  294. }
  295.  
  296. int Text::TextWidth(int, int)
  297. {
  298.     AbstractMethod("TextWidth ");
  299.     return 0;
  300. }
  301.  
  302. void Text::DrawText(int, int, Rectangle)
  303. {
  304.     AbstractMethod("DrawText ");
  305. }
  306.  
  307. void Text::DrawTextJust (int from, int to, int w, Point start, Rectangle)
  308. {
  309.     register byte ch;
  310.     int ntab, longBlanks, addSpace, seenTabs;
  311.  
  312.     if (!CheckRange(Size(), from, to))
  313.     return;
  314.  
  315.     ntab= longBlanks= seenTabs = 0;
  316.  
  317.     CalcIws(w, from, &to, &addSpace, &longBlanks, &ntab);    
  318.  
  319.     FontPtr font= SetDrawingState(from);
  320.     GrTextMoveto(start);
  321.  
  322.     for (int i = from, nBlanks = 0; i < to; i++) {
  323.     switch (ch = (*this)[i]) {
  324.     case '\t':
  325.         GrTextAdvance(Tabulate(GrGetTextPos().x-start.x));
  326.         seenTabs++;
  327.         break;
  328.     case ' ':
  329.         GrTextAdvance(font->Width(' '));
  330.         if (seenTabs == ntab) {
  331.         GrTextAdvance(addSpace);
  332.         if (nBlanks < longBlanks)
  333.             GrTextAdvance(1);
  334.         nBlanks++;
  335.         }
  336.         break;
  337.     default:
  338.         GrDrawChar(ch);
  339.         break;
  340.     }
  341.     }
  342. }
  343.  
  344. void Text::JustifiedMap(int from, int to, int w, int stopAt, int posX, 
  345.                                int *charPos, int *x)
  346. {
  347.     register byte ch;
  348.     int ntab, longBlanks, addSpace, seenTabs, cx, wx;
  349.     FontPtr font = GetFont();
  350.     if (!CheckRange(Size(), from, to))
  351.     return;
  352.  
  353.     wx= cx= ntab= longBlanks= addSpace= seenTabs= 0;
  354.  
  355.     CalcIws(w, from, &to, &addSpace, &longBlanks, &ntab);    
  356.  
  357.     for (int i = from, nBlanks = 0; i < to && i < stopAt; i++) {
  358.     switch (ch = (*this)[i]) {
  359.     case '\t':
  360.         wx = Tabulate(cx);
  361.         seenTabs++;
  362.         break;
  363.     case ' ':
  364.         wx = font->Width(' ');
  365.         if (seenTabs == ntab) {
  366.         wx += addSpace;
  367.         if (nBlanks < longBlanks)
  368.             wx++; 
  369.         nBlanks++;
  370.         }
  371.         break;
  372.     default:
  373.         wx = font->Width(ch); 
  374.         break;
  375.     }
  376.     if (cx + (wx/2) > posX)
  377.         break;
  378.     cx += wx;
  379.     }
  380.     if (x)
  381.     *x = cx;
  382.     if (charPos)
  383.     *charPos = i;
  384. }
  385.  
  386. void Text::Map(int from, int to, int stopAt, int posX, int *charPos, int *x)
  387. {
  388.     int ch,cx,wx,i;
  389.  
  390.     cx= wx= 0;
  391.  
  392.     AutoTextIter ti(this,from,to);
  393.  
  394.     for (i= from; (ch = ti(&wx)) != cEOT && i < stopAt ; i++) {
  395.     if (ch == '\t') 
  396.         wx = Tabulate(cx);
  397.     if (cx + (wx/2) > posX) 
  398.         break;
  399.     cx += wx;
  400.     }    
  401.     if (charPos)
  402.     *charPos = i;
  403.     if (x)
  404.     *x = cx;
  405. }
  406.  
  407. char *Text::AsString()
  408. {
  409.     int s= Size();
  410.     char *buf= new char[s+1];
  411.     CopyInStr((byte*)buf, s+1, 0, s);
  412.     return buf;    
  413. }
  414.  
  415. int Text::AsInt()
  416. {
  417.     int val;
  418.     if (Size() == 0)
  419.     return 0;
  420.     char *p= AsString();
  421.     sscanf(p, "%d", &val);
  422.     delete p;
  423.     return val; 
  424. }
  425.  
  426. float Text::AsFloat()
  427. {
  428.     float val;
  429.     char *p = AsString();
  430.     sscanf(p,"%f",&val);
  431.     delete p;
  432.     return val; 
  433. }
  434.  
  435. ostream& Text::PrintOnAsPureText(ostream &s)
  436. {
  437.     AbstractMethod("PrintOnAsPureText");
  438.     return s;
  439. }
  440.  
  441. istream& Text::ReadFromAsPureText(istream &s, long)
  442. {
  443.     AbstractMethod("ReadFromAsPureText");
  444.     return s;
  445. }
  446.  
  447. bool Text::IsEmpty() 
  448. {
  449.     return Size() == 0;
  450. }
  451.  
  452. int Text::GrowBy(int desiredSize)
  453. {
  454.     int s= 0;
  455.  
  456.     if (Size() >= cMaxInt)
  457.     Error("GrowBy", "cannot expand text");
  458.     else 
  459.     s= range(2, cMaxInt - desiredSize, desiredSize);
  460.     return Size()+s;
  461.  
  462. void Text::AddMark(Mark *m)
  463. {
  464.     if (marks == 0)
  465.     marks= new MarkList;
  466.     marks->Add(m);
  467. }
  468.  
  469. Mark *Text::RemoveMark(Mark *m)
  470. {
  471.     if (marks == 0)
  472.     marks= new MarkList;
  473.     return (Mark*)marks->Remove(m);
  474. }
  475.  
  476. Iterator *Text::GetMarkIter()
  477. {
  478.     if (marks == 0)
  479.     marks= new MarkList;
  480.     return marks->MakeIterator();
  481. }
  482.  
  483. MarkList *Text::GetMarkList()
  484. {
  485.     if (marks == 0)
  486.     marks= new MarkList;
  487.     return marks;
  488. }
  489.  
  490. void Text::InspectorId(char *b, int s)
  491. {
  492.     int c;
  493.     AutoTextIter next(this, 0, s-1);
  494.     for (int i= 0; (c= next()) != cEOT; i++)
  495.     b[i]= c;
  496.     b[i]= '\0';
  497. }
  498.  
  499. //---- observing ----------------------------------------------------------
  500.     
  501. Collection *Text::MakeObserverColl()
  502. {
  503.     observers= new OrdCollection(4);
  504.     return observers;
  505. }
  506.  
  507. Collection *Text::GetObservers()
  508. {    
  509.     return observers;
  510. }
  511.  
  512. void Text::DestroyObserverColl()
  513. {
  514.     SafeDelete(observers);
  515. }
  516.  
  517. void Text::SetObserverColl(Collection *cp)
  518. {
  519.     SafeDelete(observers);
  520.     observers= cp;
  521. }
  522.  
  523. //----- class TextIter ----------------------------------------------------
  524.  
  525. TextIter::TextIter(Text *s,int from,int to)
  526.     ct= s; 
  527.     ce= max(from,0); 
  528.     upto= min(to,s->Size());
  529. }
  530.  
  531. void TextIter::Reset(Text *s,int from,int to)
  532.     ct= s; 
  533.     ce= max(from,0); 
  534.     upto= min(to,s->Size());
  535. }
  536.  
  537. int TextIter::operator()(int *,LineDesc*)  
  538. {
  539.     return cEOT;
  540. }
  541.  
  542. int TextIter::operator()()  
  543. {
  544.     return cEOT;
  545. }
  546.  
  547. int TextIter::Line(LineDesc*)  
  548. {
  549.     return cEOT;
  550. }
  551.  
  552. int TextIter::GetPos()  
  553. {
  554.     return ce;
  555. }
  556.  
  557. Font *TextIter::FontAt(int)
  558.     return ct->GetFont(); 
  559.  
  560. int TextIter::Unget()
  561. {
  562.     return ce= unget;
  563. }
  564.  
  565. int TextIter::Token(int *,LineDesc*)  
  566. {
  567.     return cEOT;
  568. }
  569.  
  570. int TextIter::GetLastPos()                 // get last position
  571.     return unget; 
  572. }
  573.  
  574. void TextIter::SetPos(int newPos)
  575.     ce = newPos; 
  576. }
  577.  
  578. AutoTextIter::AutoTextIter(Text *t, int from, int to)
  579.     ti= t->MakeIterator(from,to); 
  580. }
  581.